package jude.java.money.scan;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import jude.java.money.beans.ScanFtp;
import jude.java.money.beans.Site;
import jude.java.money.provide.Provider;
import jude.java.money.service.ScanService;
import jude.java.money.spring.Services;
import jude.java.money.task.BaseTask;
import jude.java.util.I;
import jude.java.util.Utils;

public class FtpScaner extends BaseTask<Site> {
	private static final int TIMEOUT = 60 * 1000;
//	private Socket socket;
//	private byte[] request;
	private byte[] buffer;
	private String responseLine;
	private ScanService scanService;
	private static I i = new I();
	
	public FtpScaner(Provider<Site> provider) {
		super(provider);
		this.provider = provider;
		this.buffer = new byte[4096];
//		this.request = "user admin".getBytes();
		scanService = Services.getScanService();
	}

	private static int getI() {
		return i.next();
	}
	
	@Override
	protected void execute(Site site) {
		Socket socket = null;
		String host = site.getHost();
		try {
			System.out.println(getI() + " " + site.getHost());
			site.setStatus(Site.STATUS_SCANNING);
//			scanService.update(site);
			InetAddress addr = getAddress(site);
			socket = new Socket(addr, 21);
			socket.setSoTimeout(TIMEOUT);
//			OutputStream out = socket.getOutputStream();
//			out.write(request);
			int code = getReplyCode(socket, 220, null);
			if (code == 220) {
				site.setStatus(Site.STATUS_21);
				scanService.save(new ScanFtp(site.getHost(), responseLine));		//transaction
			}
//			InputStream in = socket.getInputStream();
//			int n = in.read(buffer);
//			if (n > 3) {
//				int code = Utils.getInteger(new String(buffer, 0, 3), 0);
//				if (code == 220) {	//ready
//					site.setStatus(Site.STATUS_21);
//					scanService.save(new ScanFtp(site.getHost(), new String(buffer, 4, Math.min(n, 80))));		//transaction
//				}
//				else
//					site.setStatus(Site.STATUS_NOT_FTP);
//			} else {
//				site.setStatus(Site.STATUS_NOT_FTP);
//			}
			
//			if (n > 0) {
//				System.out.println(site.getHost() + "\t" + new String(buffer, 0, n));
//			}
//			socket.close();
//			scanService.update(site);
//			return;
		} catch (ConnectException e) {
			String msg = e.getMessage();
			if (msg == null) {
				site.setStatus(Site.STATUS_CONNECT);
			} else if (msg.contains("refused")) {
				site.setStatus(Site.STATUS_REFUSED);
			} else if (msg.contains("timed out")) {
				site.setStatus(Site.STATUS_TIMEOUT2);
			} else {
				site.setStatus(Site.STATUS_CONNECT);
			}
		} catch (SocketTimeoutException e) {
			site.setStatus(Site.STATUS_TIMEOUT);
		} catch (SocketException e) {
			site.setStatus(Site.STATUS_SOCKET);
		} catch (UnknownHostException e) {
			site.setStatus(Site.STATUS_UNKNOWN_HOST);
		} catch (Throwable e) {
			site.setStatus(Site.STATUS_OTHER);
			e.printStackTrace();
		} finally {
			if (socket != null)
				try {
					socket.close();
				} catch (IOException e) {
				}
		}
		site.setHost(host);
		scanService.update(site);
	}
	
	private InetAddress getAddress(Site site) throws UnknownHostException {
		String host = site.getHost();
		try {
			return InetAddress.getByName(host);
		} catch (UnknownHostException e) {
			if (!host.startsWith("www.")) {
				InetAddress a = InetAddress.getByName("www." + host);
				site.setHost("www." + host);
				return a;
			}
			throw e;
		}
	}
	
	private int getReplyCode(Socket socket, int expect, String cmd) throws IOException {
		InputStream in = socket.getInputStream();
		int n = in.read(buffer);
		if (n > 3) {
			BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buffer, 0, n), "ISO-8859-1"));
			int code = 0;
			String line;
			while ((line = reader.readLine()) != null) {
				if (line.length() > 3) {
					int c =  Utils.getInteger(line.substring(0, 3), -1);
					if (c > 0) {
						if (c == expect) {
							responseLine = line;
							return c;
						}
						if (code > 0 && c != code) {
							if (cmd != null)
								System.out.println(cmd);
							System.out.println("response with different code : " + c + "/" + code);
						}
						code = c;
						responseLine = line;
					}
				}
			}
			if (code == 0) {
				if (cmd != null)
					System.out.println(cmd);
				System.out.println(n + "\t" + new String(buffer, 0, n - 2, "UTF-8"));
			}
			return code;
		}
		System.out.println("length: " + n);
		return 0;
	}

}
